package miggy.ui;

import miggy.utils.TextUtil;

import javax.swing.*;
import java.util.ArrayList;
import java.util.logging.Logger;

/*
//  Miggy - Java Amiga MachineCore
//  Copyright (c) 2008, Tony Headford
//  All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
//  following conditions are met:
//
//    o  Redistributions of source code must retain the above copyright notice, this list of conditions and the
//       following disclaimer.
//    o  Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
//       following disclaimer in the documentation and/or other materials provided with the distribution.
//    o  Neither the name of the Miggy Project nor the names of its contributors may be used to endorse or promote
//       products derived from this software without specific prior written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
//  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
//  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
//  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
//  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
//  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
//  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// $Revision: 21 $
*/

public class MemoryModel extends AbstractListModel
{
	private static Logger logger = Logger.getLogger(MemoryModel.class.getName());
	private static final int START_ADDR = 0;
	private static final int END_ADDR = 0x00ffffff;

	private int visibleRows;
	private int start_addr;
	private final ArrayList<MemoryBytes> items;

	public MemoryModel(int visibleRows)
	{
		this.visibleRows = visibleRows;
		this.start_addr = 0;
		items = new ArrayList<MemoryBytes>();
		fetchItems();
	}

	public final void setCurrentPos(int pos)
	{
		start_addr = pos;
		fetchItems();
	}

	public final int getCurrentPos()
	{
		return start_addr;
	}

	public final void setVisibleRows(int size)
	{
		//size changes based on the size of the JList and the number of rows
		//currently visible
		if(this.visibleRows != size)
		{
			this.visibleRows = size;
			fetchItems();
		}
	}

	public final void refresh()
	{
		fetchItems();
	}

	private void fetchItems()
	{
		//starting at current_addr disassemble until size items have been gathered
		//or we've reached the end of memory
		logger.fine("Building MemoryModel");
		int start = start_addr;
		int count = 0;
		items.removeAll(items);

		try
		{
			while((start < END_ADDR) && (count < visibleRows))
			{
				items.add(new MemoryBytes(start));
				start += 8;
				count++;
			}

			if(count < visibleRows)
			{
				for(;count < visibleRows; count++)
				{
					items.add(MemoryBytes.InvalidMemory);
				}
			}

			this.fireContentsChanged(this, 0, visibleRows);
		}
		catch(IndexOutOfBoundsException e)
		{
			logger.warning("Out of bounds building MemoryModel @ " + TextUtil.toHex(start));
		}
	}

	/**
	 * Returns the length of the list.
	 *
	 * @return the length of the list
	 */
	public int getSize()
	{
		return visibleRows;
	}

	/**
	 * Returns the value at the specified index.
	 *
	 * @param index the requested index
	 * @return the value at <code>index</code>
	 */
	public Object getElementAt(int index)
	{
		return items.get(index);
	}
}

class MemoryBytes
{
	private final int address;
	private final String mem;
	public static final MemoryBytes InvalidMemory = new MemoryBytes();

	MemoryBytes(int address)
	{
		this.address = address;
		//read 8 bytes of memory
		StringBuilder sb = new StringBuilder();
		sb.append(TextUtil.toHex(address));
		sb.append("  ");
		sb.append(TextUtil.makeMemView(address));
		mem = sb.toString();
	}

	private MemoryBytes()
	{
		address = 0;
		mem = "????????  ?? ?? ?? ?? ?? ?? ?? ??  ????????";
	}

	final int getAddress()
	{
		return address;
	}

	@Override
	public final String toString()
	{
		return mem;
	}
}

